﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SipII.Message;
using SipII.Parameter;
using SipII.Nm2000;

namespace SipII
{
    /// <summary>
    /// 针对NM2000的Sip2Server的实现代码
    /// </summary>
    partial class Sip2Server4Nm2000 : ISip2Server
    {
        #region private code

        /// <summary>
        /// 服务器是否启用错误检测
        /// </summary>
        private bool errorDetectionEnable = Properties.Settings.Default.ErrorDetectionEnable;

        /// <summary>
        /// 机构代码
        /// </summary>
        private string institutionId = Properties.Settings.Default.InstitutionId;

        /// <summary>
        /// 图书馆名称
        /// </summary>
        private string libraryName = Properties.Settings.Default.Libraryname;

        /// <summary>
        /// 返回YYYYMMDDZZZZHHMMSS格式的时间字符数组
        /// </summary>
        /// <returns></returns>
        private char[] GetDateCharArray()
        {
            return string.Format("{0}    {1}", DateTime.Now.ToString("yyyyMMdd"), DateTime.Now.ToString("HHmmss")).ToCharArray();
        }

        private char[] GetDateCharArray(DateTime dt)
        {
            return string.Format("{0}    {1}", dt.ToString("yyyyMMdd"), dt.ToString("HHmmss")).ToCharArray();
        }

        /// <summary>
        /// 进行统计计算的类型
        /// </summary>
        enum calcType { hold, charged, overdue }
        
        #endregion

        /// <summary>
        /// 返回读者状态[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string PatronStatusResponse(string sessionId, string requestCmd)
        {
            PatronStatusRequest request = new PatronStatusRequest(requestCmd);

            Session session;

            lock (Sip2ServerProxy.Sessiones)
            {
                session = Sip2ServerProxy.Sessiones[sessionId];
            }

            PatronStatusResponse response = new PatronStatusResponse();

            response.Language = Sip2Parameter.GetEnumCode(enumLanguage.Chinese).ToCharArray();
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.PatronIdentifier = request.PatronIdentifier;
            response.CurrencyType = enumCurrencyType.CNY.ToString().ToCharArray();

            if (session.LoginPassword != request.TerminalPassword)
            {
                response.PatronStatus = "              ".ToCharArray();
                response.PersonalName = "";
                response.ValidPatron = 'N';
                response.ValidPatronPassword = 'N';
                response.FeeAmount = "0";
                response.ScreenMessage = Error_TerminalPasswordNoMatch;
                response.PrintLine.Add(Error_TerminalPasswordNoMatch);
            }
            else
            {
                //获取读者状态
                nm2000DataContext dc = new nm2000DataContext();

                var readers = from t in dc.l_readers where t._读者条码 == request.PatronIdentifier select t;

                if (readers.Count() == 0)
                {
                    response.PatronStatus = "              ".ToCharArray();
                    response.PersonalName = "";
                    response.ValidPatron = 'N';
                    response.ValidPatronPassword = 'N';
                    response.FeeAmount = "0";
                    response.ScreenMessage = string.Format(Error_PatronNotExist, request.PatronIdentifier);
                    response.PrintLine.Add(string.Format(Error_PatronNotExist, request.PatronIdentifier));
                }
                else
                {
                    var reader = readers.First();

                    response.PatronStatus = getPatronStatus(reader);
                    response.PersonalName = reader._读者姓名.Trim ();
                    response.ValidPatron = 'Y';
                    response.ValidPatronPassword = 'Y';
                    response.FeeAmount = reader._欠款金额.Value.ToString();
                }
            }

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应借书操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string CheckoutResponse(string sessionId, string requestCmd)
        {
            Checkout request = new Checkout(requestCmd);

            CheckoutResponse response;

            Session session;

            lock (Sip2ServerProxy.Sessiones)
            {
                session = Sip2ServerProxy.Sessiones[sessionId];
            }

            //session = new Session();
            //session.LocationCode = "001";

            execCheckout(request, session.LocationCode, out response);

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应还书操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string CheckinResponse(string sessionId, string requestCmd)
        {
            Checkin request = new Checkin(requestCmd);

            Session session;

            lock (Sip2ServerProxy.Sessiones)
            {
                session = Sip2ServerProxy.Sessiones[sessionId];
            }

            //session = new Session();
            //session.LocationCode = "001";

            string execInfo;
            string permanentLocation;
            string titleIdentifier;
            string patronIdentifier;

            bool execSucess = execCheckin(request, session.LocationCode, out execInfo, out titleIdentifier, out permanentLocation, out patronIdentifier);

            CheckinResponse response = new CheckinResponse();

            response.Ok = execSucess ? 'Y' : 'N';
            response.Resensitize = Properties.Settings.Default.Desensitize;
            response.MagneticMedia = Properties.Settings.Default.MagneticMedia;
            response.Alert = execSucess ? 'N' : 'Y';
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.ItemIdentifier = request.ItemIdentifier;
            response.PermanentLocation = permanentLocation;

            if (execSucess)
            {
                response.TitleIdentifier = titleIdentifier;
                response.PatronIdentifier = patronIdentifier;
                response.MediaType = Sip2Parameter.GetEnumCode(enumMediaType.book).ToCharArray();
            }
            else
            {
                response.ScreenMessage = execInfo;
            }

            return response.ToString();
        }

        /// <summary>
        /// 返回ACS状态[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string AcsStatus(string sessionId, string requestCmd)
        {
            Message.ScStatus request = new ScStatus(requestCmd);

            Session session;

            lock (Sip2ServerProxy.Sessiones)
            {
                if (Sip2ServerProxy.Sessiones.ContainsKey(sessionId))
                {
                    session = Sip2ServerProxy.Sessiones[sessionId];

                    session.StatusCode = request.StatusCode;
                    session.ProtocolVersion = new string(request.ProtocolVersion);
                    session.MaxPrintWidth = new string(request.MaxPrintWidth);

                    Sip2ServerProxy.Sessiones[sessionId] = session;
                }
                else
                {
                    session = new Session();

                    session.StatusCode = request.StatusCode;
                    session.ProtocolVersion = new string(request.ProtocolVersion);
                    session.MaxPrintWidth = new string(request.MaxPrintWidth);

                    Sip2ServerProxy.Sessiones.Add(sessionId, session);
                }
            }

            Message.AcsStatus response = new AcsStatus();

            response.OnlineStatus = 'Y';
            response.CheckinOk = Properties.Settings.Default.Checkin_Enable ? 'Y' : 'N';
            response.CheckoutOk = Properties.Settings.Default.Checkout_Enable ? 'Y' : 'N';
            response.AcsRenewalPolicy = Properties.Settings.Default.Renew_Enable ? 'Y' : 'N';
            response.StatusUpdateOk = Properties.Settings.Default.ItemStatusUpdate_Enable ? 'Y' : 'N';
            response.OfflineOk = 'N';
            response.TimeoutPeriod = "999".ToCharArray();
            response.RetriesAllowed = "999".ToCharArray();
            response.DatetimeSync = GetDateCharArray();
            response.ProtocolVersion = "2.00".ToCharArray();
            response.InstitutionId = institutionId;
            response.LibraryName = libraryName;
            response.SupportedMessages = new string(getSupportedMessage());
            response.TerminalLocation = session.TerminalLocation;

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应登录操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string LoginResponse(string sessionId, string requestCmd)
        {
            Login request = new Login(requestCmd);

            string terminalLocation;

            bool execSucess = execLogin(sessionId, request, out terminalLocation);

            if (execSucess)
            {
                Session terminal = new Session();

                terminal.LocationCode = request.LocationCode;
                terminal.LoginUserId = request.LoginUserId;
                terminal.LoginPassword = request.LoginPassword;
                terminal.TerminalLocation = terminalLocation;

                lock (Sip2ServerProxy.Sessiones)
                {
                    if (Sip2ServerProxy.Sessiones.ContainsKey(sessionId))
                    {
                        Sip2ServerProxy.Sessiones[sessionId] = terminal;
                    }
                    else
                    {
                        Sip2ServerProxy.Sessiones.Add(sessionId, terminal);
                    }
                }
            }

            LoginResponse response = new LoginResponse();

            response.Ok = execSucess ? '1' : '0';

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 返回读者信息[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string PatronInformationResponse(string sessionId, string requestCmd)
        {
            PatronInformation request = new PatronInformation(requestCmd);

            Session session;

            //lock (Sip2ServerProxy.Sessiones)
            //{
            //    session = Sip2ServerProxy.Sessiones[sessionId];
            //}

            PatronInformationResponse response = new PatronInformationResponse();

            response.Language = Sip2Parameter.GetEnumCode(enumLanguage.Chinese).ToCharArray();
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.PatronIdentifier = request.PatronIdentifier;
            response.CurrencyType = enumCurrencyType.CNY.ToString().ToCharArray();

            response.FineItemsCount = "    ".ToCharArray();
            response.RecallItemsCount = "    ".ToCharArray();
            response.UnavailableHoldsCount = "    ".ToCharArray();

            nm2000DataContext dc = new nm2000DataContext();

            var readers = from t in dc.l_readers where t._读者条码 == request.PatronIdentifier select t;

            if (readers.Count() == 0)
            {
                response.PatronStatus = "              ".ToCharArray();
                response.HoldItemsCount = "    ".ToCharArray();
                response.OverdueItemsCount = "    ".ToCharArray();
                response.ChargedItemsCount = "    ".ToCharArray();
                response.PersonalName = "";
                response.ValidPatron = 'N';
                response.ValidPatronPassword = 'N';

                response.ScreenMessage = Error_PatronNotExist;
            }
            else
            {
                var reader = readers.First();

                response.PatronStatus = getPatronStatus(reader);
                response.HoldItemsCount = getItemsCount(reader, calcType.hold);
                response.OverdueItemsCount = getItemsCount(reader, calcType.overdue);
                response.ChargedItemsCount = getItemsCount(reader, calcType.charged);

                response.HoldItemsLimit = getLimitCout(reader, calcType.hold);
                response.ChargedItemsLimit = getLimitCout(reader, calcType.charged);
                response.OverdueItemsLimit = string.IsNullOrEmpty(Properties.Settings.Default.Overdue_Limit) ? "    ".ToCharArray() : Properties.Settings.Default.Overdue_Limit.ToCharArray();
                response.FeeLimit = string.IsNullOrEmpty(Properties.Settings.Default.Fee_Limit) ? "    " : Properties.Settings.Default.Fee_Limit;

                response.PersonalName = reader._读者姓名.Trim ();
                response.ValidPatron = 'Y';
                response.ValidPatronPassword = 'Y';
                response.FeeAmount = (reader._欠款金额 == null ? 0 : reader._欠款金额.Value).ToString("G");

                response.HoldItems = getItems(reader, calcType.hold);
                response.ChargedItems = getItems(reader, calcType.charged);
                response.OverdueItems = getItems(reader, calcType.overdue);
            }

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应结束读者会话操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string EndSessionResponse(string sessionId, string requestCmd)
        {
            EndPatronSession request = new EndPatronSession();

            lock (Sip2ServerProxy.Sessiones)
            {
                if (Sip2ServerProxy.Sessiones.ContainsKey(sessionId))
                {
                    Sip2ServerProxy.Sessiones[sessionId].PatronIdentifier = "";
                    Sip2ServerProxy.Sessiones[sessionId].PatronPassword = "";
                }
            }

            EndSessionResponse response = new EndSessionResponse();

            response.EndSession = 'Y';
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.PatronIdentifier = request.PatronIdentifier;

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应缴费操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string FeePaidResponse(string sessionId, string requestCmd)
        {
            FeePaid request = new FeePaid(requestCmd);

            string execInfo;

            //操作是否成功
            bool execSucess = execFeePaid(request, out execInfo);

            //返回结果
            FeePaidResponse response = new FeePaidResponse();

            response.PaymentAccepted = execSucess ? 'Y' : 'N';
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.PatronIdentifier = request.PatronIdentifier;
            response.TransactionId = request.TransactionId;
            response.ScreenMessage = execInfo;
            response.PrintLine.Add(execInfo);

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 返回图书信息[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string ItemInformationResponse(string sessionId, string requestCmd)
        {
            ItemInformation request = new ItemInformation(requestCmd);

            ItemInformationResponse response = new ItemInformationResponse();

            nm2000DataContext dc = new nm2000DataContext();

            var codebar = (from t in dc.l_codebars where t._图书条码 == request.ItemIdentifier select t).FirstOrDefault();

            if (codebar == null)
            {
                response.CirculationStatus = ((int)enumCirculationstatus.missing).ToString("D2").ToCharArray();
                response.TitleIdentifier = "";
                response.ScreenMessage = string.Format(Error_ItemNotExist, request.ItemIdentifier);
            }
            else
            {
                var bib = (from t in dc.bibs where t.recid == codebar.recid select t).FirstOrDefault();

                response.CirculationStatus = getCirculationStatus(codebar._状态标识.Value);
                response.TitleIdentifier = bib._题名;
                response.Owner = libraryName;
                response.CurrencyType = enumCurrencyType.CNY.ToString().ToCharArray();
                response.FeeAmount = bib._价格.ToString();
                response.MediaType = ((int)enumMediaType.book).ToString("D3").ToCharArray();
                response.PermanentLocation = string.Format("{0}/{1}", string.IsNullOrEmpty(bib._分类) ? "" : bib._分类.Trim()
                                , string.IsNullOrEmpty(bib._书次) ? "" : bib._书次);

                var loan = (from t in dc.l_loans where t._图书条码 == request.ItemIdentifier select t).FirstOrDefault();

                if (loan != null)
                {
                    response.DueDate = new string(GetDateCharArray(loan._应还日期.Value));
                }
            }

            response.SecurityMarker = Properties.Settings.Default.SecurityMarker.ToCharArray();
            response.FeeType = ((int)enumFeeType.other_unknown).ToString("D2").ToCharArray();
            response.TransactionDate = GetDateCharArray();
            response.ItemIdentifier = request.ItemIdentifier;

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应修改图书状态操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string ItemStatusUpdateResponse(string sessionId, string requestCmd)
        {
            ItemStatusUpdate request = new ItemStatusUpdate(requestCmd);

            //操作失败提示信息
            string execInfo;

            //操作是否成功
            bool execSucess = execItemStatusUpdate(request, out execInfo);

            ItemStatusUpdateResponse response = new ItemStatusUpdateResponse();

            response.ItemPropertiesOk = execSucess ? '1' : '0';
            response.TransactionDate = GetDateCharArray();
            response.ItemIdentifier = request.ItemIdentifier;
            response.ItemProperties = request.ItemProperties;
            response.ScreenMessage = execInfo;

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();

        }

        /// <summary>
        /// 响应启用读者操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string PatronEnableResponse(string sessionId, string requestCmd)
        {
            PatronEnable request = new PatronEnable(requestCmd);

            Session session;

            lock (Sip2ServerProxy.Sessiones)
            {
                session = Sip2ServerProxy.Sessiones[sessionId];
            }

            PatronEnableResponse response = new PatronEnableResponse();

            response.Language = Sip2Parameter.GetEnumCode(enumLanguage.Chinese).ToCharArray();
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.PatronIdentifier = request.PatronIdentifier;

            if (session.LoginPassword != request.TerminalPassword)
            {
                response.PatronStatus = "              ".ToCharArray();
                response.PersonalName = "";
                response.ValidPatron = 'N';
                response.ValidPatronPassword = 'N';
                response.ScreenMessage = Error_TerminalPasswordNoMatch;
                response.PrintLine.Add(Error_TerminalPasswordNoMatch);
            }
            else
            {
                //获取读者状态
                nm2000DataContext dc = new nm2000DataContext();

                dc.ExecuteCommand("UPDATE l_reader SET _证件状态 = '正常' WHERE _读者条码='{0}'", request.PatronIdentifier);

                var readers = from t in dc.l_readers where t._读者条码 == request.PatronIdentifier select t;

                if (readers.Count() == 0)
                {
                    response.PatronStatus = "              ".ToCharArray();
                    response.PersonalName = "";
                    response.ValidPatron = 'N';
                    response.ValidPatronPassword = 'N';
                    response.ScreenMessage = string.Format(Error_PatronNotExist, request.PatronIdentifier);
                    response.PrintLine.Add(string.Format(Error_PatronNotExist, request.PatronIdentifier));
                }
                else
                {
                    var reader = readers.First();

                    response.PatronStatus = getPatronStatus(reader);
                    response.PersonalName = reader._读者姓名.Trim ();
                    response.ValidPatron = 'Y';
                    response.ValidPatronPassword = 'Y';
                }
            }

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应预约操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string HoldResponse(string sessionId, string requestCmd)
        {
            Hold request = new Hold(requestCmd);

            string execInfo;

            bool execSucess = execHold(request, out execInfo);

            HoldResponse response = new HoldResponse();

            if (!execSucess)
            {
                response.Ok = '0';
                response.Available = 'N';
                response.TransactionDate = GetDateCharArray();
                response.InstitutionId = institutionId;
                response.PatronIdentifier = request.PatronIdentifier;
                response.ScreenMessage = execInfo;
                response.PrintLine.Add(execInfo);
            }

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应单本续借操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string RenewResponse(string sessionId, string requestCmd)
        {
            Renew request = new Renew(requestCmd);

            RenewResponse response = new RenewResponse();

            string itemTitle;       //文献标题
            string dueDate;         //超期时间
            string execInfo;        //执行反馈信息

            bool renewalOk = execRenew(request.PatronIdentifier, request.ItemIdentifier, out itemTitle, out dueDate, out execInfo);

            response.Ok = renewalOk ? '1' : '0';
            response.RenewalOk = renewalOk ? '1' : '0';
            response.TitleIdentifier = itemTitle;
            response.DueDate = dueDate;
            response.MagneticMedia = Properties.Settings.Default.MagneticMedia;
            response.Desensitize = Properties.Settings.Default.Desensitize;
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.PatronIdentifier = request.PatronIdentifier;
            response.ItemIdentifier = request.ItemIdentifier;
            response.FeeType = Sip2Parameter.GetEnumCode(enumFeeType.other_unknown).ToCharArray();

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 响应全部续借操作[0]
        /// </summary>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string RenewAllResponse(string sessionId, string requestCmd)
        {
            RenewAll request = new RenewAll(requestCmd);

            nm2000DataContext dc = new nm2000DataContext();

            var loans = from t in dc.l_loans where t._读者条码 == request.PatronIdentifier select t._图书条码;

            int renewed = 0;
            int unrenewed = 0;

            string itemTitle;       //文献标题
            string dueDate;         //超期时间
            string execInfo;        //执行反馈信息

            List<string> renewedItems = new List<string>() { };
            List<string> unrenewedItems = new List<string>() { };

            foreach (var itemId in loans)
            {
                bool renewalOk = execRenew(request.PatronIdentifier, itemId, out itemTitle, out dueDate, out execInfo);

                if (renewalOk)
                {
                    renewed++;
                    renewedItems.Add(itemId);
                }
                else
                {
                    unrenewed++;
                    unrenewedItems.Add(itemId);
                }
            }

            RenewAllResponse response = new RenewAllResponse();

            response.Ok = '1';
            response.RenewedCount = renewed.ToString("D4").ToCharArray();
            response.UnrenewedCount = unrenewed.ToString("D4").ToCharArray();
            response.TransactionDate = GetDateCharArray();
            response.InstitutionId = institutionId;
            response.RenewedItems = renewedItems;
            response.UnrenewedItems = unrenewedItems;
            response.ScreenMessage = string.Format(Info_Renewall, renewed, unrenewed);

            if (errorDetectionEnable)
                response.Sequence = request.Sequence;

            return response.ToString();
        }

        /// <summary>
        /// 停用读者账号[0]
        /// </summary>
        /// <param name="sessionId"></param>
        /// <param name="requestCmd"></param>
        /// <returns></returns>
        public string BlockPatronResponse(string sessionId, string requestCmd)
        {
            BlockPatron request = new BlockPatron(requestCmd);

            if (request.CardRetained == 'Y')
            {
                nm2000DataContext dc = new nm2000DataContext();

                dc.ExecuteCommand("UPDATE l_reader SET _证件状态 = '挂失' WHERE _读者条码='{0}'", request.PatronIdentifier);
            }

            return PatronStatusResponse(sessionId, requestCmd);
        }
    }
}
